package modelo.delictivas;


import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import modelo.ExceptionDatosFaltantes;
import modelo.caracteristicas.Cabello;
import modelo.caracteristicas.Hobby;
import modelo.caracteristicas.Senia;
import modelo.caracteristicas.Sexo;
import modelo.caracteristicas.Vehiculo;
import modelo.policiales.Rango;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class OrganizacionDelictiva {

	private List<Ladron> ladronesAsociados;
	private String nombre;
	private List<TesoroNacionalComun> tesorosComunes;
	private List<TesoroNacionalValioso> tesorosValiosos;
	private List<TesoroNacionalMuyValioso> tesorosMuyValiosos;

	public OrganizacionDelictiva(String nombre) {
		this.nombre = nombre;
		this.ladronesAsociados = new ArrayList<Ladron>();
		this.tesorosComunes = new ArrayList<TesoroNacionalComun>();
		this.tesorosValiosos = new ArrayList<TesoroNacionalValioso>();
		this.tesorosMuyValiosos = new ArrayList<TesoroNacionalMuyValioso>();
	}

	public void asociarLadron(Ladron ladron) {
		this.ladronesAsociados.add(ladron);
	}

	public boolean ladronEstaAsociado(Ladron ladron) {
		return this.ladronesAsociados.contains(ladron);
	}

	public String getNombre() {
		return nombre;
	}

	public void agregarTesoroARobar(TesoroNacionalComun tesoro) {
		this.tesorosComunes.add(tesoro);
	}
	
	public void agregarTesoroARobar(TesoroNacionalValioso tesoro) {
		this.tesorosValiosos.add(tesoro);
	}
	
	public void agregarTesoroARobar(TesoroNacionalMuyValioso tesoro) {
		this.tesorosMuyValiosos.add(tesoro);
	}
	
	public int getCantidadDeTesorosARobar() {
		return (this.tesorosComunes.size() 
				+ this.tesorosMuyValiosos.size() 
				+ this.tesorosValiosos.size());
	}

	public Robo generarRoboSegunRango(Rango rango) throws Exception {
		
		Ladron ladronElegido = this.elegirLadron();
		TesoroNacional tesoro = this.elegirTesoroSegunRango(rango);
		
		return ladronElegido.robarTesoro(tesoro);
	}

	private TesoroNacional elegirTesoroSegunRango(Rango rango) {
		return rango.obtenerTesoroNacionalCorrespondiente(this);
	}

	private Ladron elegirLadron() {
		Random randomGenerator = new Random();
		int i = randomGenerator.nextInt( ( ladronesAsociados.size() ));
		
		return ladronesAsociados.get(i);
	}

	public TesoroNacional obtenerTesoroNacionalComun() {
		Random randomGenerator = new Random();
		int i = randomGenerator.nextInt( ( tesorosComunes.size() ));
		
		return tesorosComunes.get(i);
	} 
	
	public TesoroNacional obtenerTesoroNacionalValioso() {
		Random randomGenerator = new Random();
		int i = randomGenerator.nextInt( ( tesorosValiosos.size() ));
		
		return tesorosValiosos.get(i);
	} 
	
	public TesoroNacional obtenerTesoroNacionalMuyValioso() {
		Random randomGenerator = new Random();
		int i = randomGenerator.nextInt( ( tesorosMuyValiosos.size() ));
		
		return tesorosMuyValiosos.get(i);
	} 

	public Ladron obtenerLadronConCaracteristicas(Sexo sexo, Cabello cabello,
			Vehiculo vehiculo, Senia senia, Hobby hobby) {
		
		List<Ladron> ladronesFiltrados = new ArrayList<Ladron>();
		ladronesFiltrados.addAll(this.ladronesAsociados);
		
		Iterator<Ladron> it = ladronesFiltrados.iterator();
		
        while( it.hasNext()  )
		{
        	Ladron ladron = it.next();
        	
        	//Va removiendo si no coinciden, hasta que quede el o los que coincidan
        	//Si se le pasa null no lo toma en cuenta, compara segun datos verdaderos
        	
			if ( (ladron.getSexo()!= sexo) && (sexo != null)){
				ladronesFiltrados.remove(ladron);
				it = ladronesFiltrados.iterator();
			}
			else if ((ladron.getColorDeCabello()!= cabello) && (cabello != null)){
				ladronesFiltrados.remove(ladron);
				it = ladronesFiltrados.iterator();
			}
			else if ((ladron.getVehiculo()!= vehiculo) && (vehiculo != null)){
				ladronesFiltrados.remove(ladron);
				it = ladronesFiltrados.iterator();
			}
			else if ((ladron.getSenia()!= senia) && (senia != null)){
				ladronesFiltrados.remove(ladron);
				it = ladronesFiltrados.iterator();
			}
			else if ((ladron.getHobby()!= hobby) && (hobby != null)){
				ladronesFiltrados.remove(ladron);
				it = ladronesFiltrados.iterator();
			}
		}	
        
		if (ladronesFiltrados.size() == 1)
			return ladronesFiltrados.get(0);
		else
			return null;
		//Por ahora devuelve null si es mas de un ladron los que encuentra
		//Que tambien puede considerarse que no lo encontro al que buscaba
		
	}

	
	public Element serializar(Document doc) {
		
		Element elementoOrganizacion = doc.createElement("OrganizacionDelictiva");
		elementoOrganizacion.setAttribute("Nombre", this.nombre);
		
		Element elementoTesorosComunes = doc.createElement("TesorosComunes");
		elementoOrganizacion.appendChild(elementoTesorosComunes);
		for (TesoroNacionalComun tesoroComun : this.tesorosComunes) {
			elementoTesorosComunes.appendChild(tesoroComun.serializar(doc));
		}
		
		Element elementoTesorosValiosos = doc.createElement("TesorosValiosos");
		elementoOrganizacion.appendChild(elementoTesorosValiosos);
		for (TesoroNacionalValioso tesoroValioso : this.tesorosValiosos) {
			elementoTesorosValiosos.appendChild(tesoroValioso.serializar(doc));
		}
		
		Element elementoTesorosMuyValiosos = doc.createElement("TesorosMuyValiosos");
		elementoOrganizacion.appendChild(elementoTesorosMuyValiosos);
		for (TesoroNacionalMuyValioso tesoroMuyValioso : this.tesorosMuyValiosos) {
			elementoTesorosMuyValiosos.appendChild(tesoroMuyValioso.serializar(doc));
		}
		
		Element elementoLadrones = doc.createElement("Ladrones");
		elementoOrganizacion.appendChild(elementoLadrones);
		for (Ladron ladron : this.ladronesAsociados) {
			elementoLadrones.appendChild(ladron.serializar(doc));
		}
		
		return elementoOrganizacion;
	}
	
	public static OrganizacionDelictiva hidratar(Document doc) throws Exception {
	
		Element elementoOrganizacion = (Element) doc.getElementsByTagName("OrganizacionDelictiva").item(0);
		
		String nombre = elementoOrganizacion.getAttribute("Nombre");
		OrganizacionDelictiva organizacionNueva = new OrganizacionDelictiva(nombre);
		
		Element elementoTesorosComunes = (Element)elementoOrganizacion.getElementsByTagName("TesorosComunes").item(0);
		
		for(int i=0; i< elementoTesorosComunes.getChildNodes().getLength(); i++) {
			TesoroNacionalComun tesoroComun = TesoroNacionalComun.hidratar((Element) elementoTesorosComunes.getChildNodes().item(i));
			organizacionNueva.agregarTesoroARobar(tesoroComun);
		}
		
		Element elementoTesorosValiosos = (Element)elementoOrganizacion.getElementsByTagName("TesorosValiosos").item(0);
		
		for(int i=0; i< elementoTesorosValiosos.getChildNodes().getLength(); i++) {
			TesoroNacionalValioso tesoroValioso = TesoroNacionalValioso.hidratar((Element) elementoTesorosValiosos.getChildNodes().item(i));
			organizacionNueva.agregarTesoroARobar(tesoroValioso);
		}
		
		Element elementoTesorosMuyValiosos = (Element)elementoOrganizacion.getElementsByTagName("TesorosMuyValiosos").item(0);
		
		for(int i=0; i< elementoTesorosMuyValiosos.getChildNodes().getLength(); i++) {
			TesoroNacionalMuyValioso tesoroMuyValioso = TesoroNacionalMuyValioso.hidratar((Element) elementoTesorosMuyValiosos.getChildNodes().item(i));
			organizacionNueva.agregarTesoroARobar(tesoroMuyValioso);
		}
		
		Element elementoLadrones = (Element)elementoOrganizacion.getElementsByTagName("Ladrones").item(0);
		
		for(int i=0; i< elementoLadrones.getChildNodes().getLength(); i++) {
			Ladron ladron = Ladron.hidratar((Element) elementoLadrones.getChildNodes().item(i));
			organizacionNueva.asociarLadron(ladron);
		}
		
		return organizacionNueva;
	}

	public int cantidadDeLadronesAsociados() {
		return this.ladronesAsociados.size();
	}

	public static OrganizacionDelictiva cargarDeXML(String string) throws Exception {			
		
		File file = new File(string);
		if(!file.exists())
			throw new ExceptionDatosFaltantes("No existe archivo " + string + " necesario para la carga de la aplicacion");
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.newDocument();
		
		doc = dBuilder.parse(string);
		doc.getDocumentElement().normalize();
		
		return OrganizacionDelictiva.hidratar(doc);
	}

}
